/***********************************************
 This file is part of redia-bapps-main-ios.
 
 Copyright (c) 2015 Redia A/S
 
 Redia-bapps-main-ios is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 Redia-bapps-main-ios is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with redia-bapps-main-ios.  If not, see <http://www.gnu.org/licenses/>.
 
 *********************************************** */

//
//  BAScanFrontViewController.m
//  redia-bapps-ios
//
//  Created by Henrik Lynbech on 11/11/13.
//  Copyright (c) 2013 redia. All rights reserved.
//

#import "BAScanFrontViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "BALightFrameButton.h"
#import "BALibrarySettings.h"
#import "BAPatronSettings.h"
#import "UIImage+MultiplyColor.h"
#import "BAFullRecord.h"
#import "BAMaterialViewController.h"
#import "BARootViewController.h"
#import "BAWebBrowserViewController.h"

#ifdef BA_IMF_BUILD
#import "IMFRPCManager.h"
#import "IMFPackageMaterialsViewController.h"
#endif

@interface BAScanFrontViewController () {
    SystemSoundID cameraSoundRef;
    BOOL isScannerRunning;
}

@property (strong, nonatomic) IBOutlet UIView *infoPopupView;
@property (weak, nonatomic) IBOutlet UILabel *infoLabel1;
@property (weak, nonatomic) IBOutlet UILabel *infoLabel2;
@property (weak, nonatomic) IBOutlet BALightFrameButton *startScanButton;
@property (weak, nonatomic) IBOutlet BALightFrameButton *checkMarkButton;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingIndicator;

//ipad
@property (weak, nonatomic) IBOutlet UIImageView *crossHairIPadTR;
@property (weak, nonatomic) IBOutlet UIImageView *crossHairIPadBR;
@property (weak, nonatomic) IBOutlet UIImageView *crossHairIPadBL;

//ios7 scanner framework properties
@property (strong, nonatomic) AVCaptureDevice* device;
@property (strong, nonatomic) AVCaptureDeviceInput* input;
@property (strong, nonatomic) AVCaptureSession* session;
@property (strong, nonatomic) AVCaptureMetadataOutput* output;
@property (strong, nonatomic) AVCaptureVideoPreviewLayer* preview;

@end

@implementation BAScanFrontViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    RD_SET_EDGES_FOR_EXTENDED_LAYOUT_IOS7;
    
    BA_FLYOUT_MENU_ADD_BUTTON(BASpecialNavigationBarConfigurationDefault)

    NSURL* soundurl = [[NSBundle mainBundle] URLForResource:@"scanner_code_scanner_sound.wav" withExtension:nil];
    OSStatus error = AudioServicesCreateSystemSoundID((__bridge CFURLRef)(soundurl),&cameraSoundRef);
    if (error!=noErr) {
        ALog(@"Error loading scanner sound file: %ld",error);
    }

    if (RD_IS_IPAD) {
        
        self.crossHairIPadTR.transform = CGAffineTransformMakeRotation(M_PI_2);
        self.crossHairIPadBR.transform = CGAffineTransformMakeRotation(M_PI);
        self.crossHairIPadBL.transform = CGAffineTransformMakeRotation(3.0*M_PI_2);
        
        if (![[BAPatronSettings instance] userSelectedDontShowScannerIntro] && !self.dontShowUserIntroHelp) {
            [self showInfoPopup];
        }
        
        [self setupScannerView];
        [self.loadingIndicator performSelector:@selector(stopAnimating) withObject:nil afterDelay:0.1];
        
    } else {
        //iphone setup
        if (![[BAPatronSettings instance] userSelectedDontShowScannerIntro] && !self.dontShowUserIntroHelp) {
            [self showInfoPopup];
            [self.loadingIndicator stopAnimating];
        } else {
            [self setupScannerView];
            [self.loadingIndicator performSelector:@selector(stopAnimating) withObject:nil afterDelay:0.1];
        }
    }
}

-(void)setScannerViewOrientation:(UIDeviceOrientation)toOrientation
{
    if ([BAUtils instance].iOSMajorVersion >= 7) {
        if (RD_IS_IPAD) {
            if([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) {
                AVCaptureConnection *con = self.preview.connection;
                con.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
            } else {
                AVCaptureConnection *con = self.preview.connection;
                con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
            }

        } else {
            //assume portrait on iphone
            AVCaptureConnection *con = self.preview.connection;
            con.videoOrientation = AVCaptureVideoOrientationPortrait;
        }
        
    } else {
        //zbar impl for ios <= 6
#ifdef BA_USE_ZBAR_SCANNER
        if (RD_IS_IPAD) {
            if (toOrientation == UIDeviceOrientationLandscapeLeft) {
                [self.readerView setPreviewTransform:CGAffineTransformMakeRotation(-M_PI_2)];
                self.readerView.zoom=1;
            } else if (toOrientation == UIDeviceOrientationLandscapeRight) {
                [self.readerView setPreviewTransform:CGAffineTransformMakeRotation(M_PI_2)];
                self.readerView.zoom=1;
            }
        }
#endif
    }
}

-(void)setupScannerView
{
    if ([BAUtils instance].iOSMajorVersion >= 7) {
        if(!TARGET_IPHONE_SIMULATOR) {
            self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
            
            self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
            
            if (self.input==nil) {
                UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Kan ikke åbne kameraet" message:@"Du skal give adgang til kameraet for at kunne scanne bøger." delegate:self
                                                      cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [alert show];
                self.device=nil;
                return;
            }
            
            self.session = [[AVCaptureSession alloc] init];
            
            self.output = [[AVCaptureMetadataOutput alloc] init];
            [self.session addOutput:self.output];
            [self.session addInput:self.input];
            
            [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
            self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode128Code];
            
            self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
            self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
            self.preview.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
            
            AVCaptureConnection *con = self.preview.connection;
            if (RD_IS_IPAD) {
                con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
            } else {
                //iphone
                con.videoOrientation = AVCaptureVideoOrientationPortrait;
            }
            
            [self.scanContainerView.layer insertSublayer:self.preview atIndex:0];
        } else {
            DLog(@"Won't open scanner view on simulator");
        }
        
    } else {
        //zbar impl for ios <= 6
#ifdef BA_USE_ZBAR_SCANNER
        self.readerView = [ZBarReaderView new];
        
        
        
        [self.scanContainerView addSubview:self.readerView];
        [BAUtils setViewToFillParent:self.readerView];
        
        self.readerView.torchMode = AVCaptureTorchModeOff;
        self.readerView.allowsPinchZoom = NO;
        
        self.readerView.readerDelegate = self;
        self.readerView.zoom=1;
        
        // you can use this to support the simulator
        if(TARGET_IPHONE_SIMULATOR) {
            cameraSim = [[ZBarCameraSimulator alloc]
                         initWithViewController: self];
            cameraSim.readerView = self.readerView;
        }
#endif
    }
    [self setScannerViewOrientation:[[UIDevice currentDevice] orientation]];
}

-(void)showInfoPopup
{
    [self.view addSubview:self.infoPopupView];

    if (RD_IS_IPAD) {
        /* was:
        BA_LABEL_SET_FONT_REGULAR_WITH_SIZE(self.infoLabel1,11);
        BA_LABEL_SET_FONT_REGULAR_WITH_SIZE(self.infoLabel2,11);
        BA_LABEL_SET_FONT_REGULAR_WITH_SIZE(self.startScanButton.titleLabel, 11);

        [self.startScanButton setTitle:@"LUK" forState:UIControlStateNormal];
        [self.infoLabel1 setText:@"HOLD IPAD'ENS KAMERA HEN OVER KODEN\nOG AFVENT LYD"];
         */
         
        self.infoPopupView.alpha = 0.8;
        self.infoPopupView.translatesAutoresizingMaskIntoConstraints=NO;
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[infoPopupView(100)]-25-|"
                                                                          options:0
                                                                          metrics:0
                                                                            views:@{@"infoPopupView":self.infoPopupView,
                                                                                    
                                                                                    }]];


        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-200-[infoPopupView]-200-|"
                                                                          options:0
                                                                          metrics:0
                                                                            views:@{@"infoPopupView":self.infoPopupView,
                                                                                    
                                                                                    }]];

    } else {
        //iphone setup for infoview
        [BAUtils setViewToFillParent:self.infoPopupView];
        
        BA_LABEL_SET_FONT_REGULAR(self.infoLabel1);
        BA_LABEL_SET_FONT_REGULAR(self.infoLabel2);

    }

  }

- (IBAction)startScanClicked:(id)sender {
    CGRect animframe = self.infoPopupView.frame;
    animframe.origin.y += self.view.bounds.size.height;
    [UIView animateWithDuration:0.5
                     animations:^{
                         self.infoPopupView.frame = animframe;
                     }
                     completion:^(BOOL finished) {
                         [self.infoPopupView removeFromSuperview];
                     }
     ];
    
    if (!RD_IS_IPAD) {
        [self setupScannerView];
        [self startScannerScanning]; //[self.readerView start];
    }

    [self.loadingIndicator startAnimating];
    [self.loadingIndicator performSelector:@selector(stopAnimating) withObject:nil afterDelay:0.5];

}

-(void)startScannerScanning
{
    isScannerRunning=YES;
    if ([BAUtils instance].iOSMajorVersion >= 7) {
        [self.session startRunning];
    } else {
        //ios 6 zbar
#ifdef BA_USE_ZBAR_SCANNER
        [self.readerView start];
#endif
    }
}

-(void)stopScannerScanning
{
    isScannerRunning=NO;
    if ([BAUtils instance].iOSMajorVersion >= 7) {
        [self.session stopRunning];
    } else {
        //ios 6 zbar
#ifdef BA_USE_ZBAR_SCANNER
        [self.readerView stop];
#endif
    }
}


- (IBAction)checkMarkClicked:(id)sender {
    BOOL dontShow = ! [[BAPatronSettings instance] userSelectedDontShowScannerIntro];
    if (dontShow) {
        [self showCheckMark];
    } else {
        [self clearCheckMark];
    }
    [[BAPatronSettings instance] setUserSelectedDontShowScannerIntro:dontShow];
}

-(void)showCheckMark
{
    UIColor *checkmarkColor = [[BALibrarySettings instance] getCustomerColorNormal];
    if (checkmarkColor == nil) {
        checkmarkColor = [UIColor blackColor];
    }
    [self.checkMarkButton setImage:[UIImage imageNamed:@"login-checkmark" multiplyWithColor:checkmarkColor] forState:UIControlStateNormal];

}

-(void)clearCheckMark
{
    [self.checkMarkButton setImage:nil forState:UIControlStateNormal];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) cleanup
{
#ifdef BA_USE_ZBAR_SCANNER
    cameraSim = nil;
    _readerView.readerDelegate = nil;
    _readerView = nil;
#endif
}

- (void) dealloc
{
    [self cleanup];
    [BARPCManager closeConnectionsForView:self];
}


- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient
                                 duration: (NSTimeInterval) duration
{
    [super willRotateToInterfaceOrientation:orient duration:duration];
    
    /* doesnt work on iPad+iOS7
    // compensate for view rotation so camera preview is not rotated
    [self.readerView willRotateToInterfaceOrientation: orient
                                        duration: duration];
     */
    [self setScannerViewOrientation:(UIDeviceOrientation) orient];
}


- (void) viewDidAppear: (BOOL) animated
{
    // run the reader when the view is visible
    DLog(@"viewDidAppear");
    self.scanContainerView.hidden=NO;
    [self startScannerScanning];
    [self.loadingIndicator stopAnimating];

}

- (void) viewWillDisappear: (BOOL) animated
{
    DLog(@"viewWillDisappear");
    [self stopScannerScanning]; //[self.readerView stop];
}

-(void)scannerScannedCode:(BAScannerCodeType)codetype value:(NSString*)value
{
    if (!isScannerRunning) {
        return;
    }
    
    if (self.scannerResultDelegate) {
        //handling by delegate
        [self.scannerResultDelegate scannerScannedCode:codetype value:value];
        
    } else {
        //if no delegate, open material view or IMF package
        if (codetype==BAScannerCodeTypeQRCode) {
            [self playSnapShotSound];
            

#ifdef BA_IMF_BUILD
            NSMutableDictionary *params = [NSMutableDictionary new];
            for (NSString *split in [value componentsSeparatedByString:@"?"]) {
                for (NSString *param in [split componentsSeparatedByString:@"&"]) {
                    NSArray *elts = [param componentsSeparatedByString:@"="];
                    if([elts count] < 2) continue;
                    [params setObject:[elts objectAtIndex:1] forKey:[elts objectAtIndex:0]];
                }
            }
            
            NSString* packageId = [params objectForKey:@"pid"];

            if (packageId == nil) {
                [[[UIAlertView alloc] initWithTitle:@"Ugyldig QR kode" message:@"Denne QR kode er ikke undestøttet" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil] show];
                return;
            }
            
            
            [self stopScannerScanning]; //[self.readerView stop];
            
            DLog(@"found packageID");
            [self.loadingIndicator startAnimating];
            [IMFRPCManager getPackageAsyncFromView:self packageId:packageId result:^(IMFPackage *package) {
                [self.loadingIndicator stopAnimating];
//                if (RD_IS_IPAD) {
//                    BASlideInViewController* slideIn = [BASlideInViewController findSlideInViewController:self];
//                    if (slideIn != nil) {
//                        IMFPackageMaterialsViewController* packageViewController = [IMFPackageMaterialsViewController new];
//                        packageViewController.imfPackage = package;
//                        [slideIn slideInViewController:packageViewController animated:YES completion:nil];
//                    }
//                }
//                else{
                    if (self.navigationController != nil && package != nil) {
                        IMFPackageMaterialsViewController* packageViewController = [IMFPackageMaterialsViewController new];
                        packageViewController.imfPackage = package;
                        [self.navigationController pushViewController:packageViewController animated:YES];
                    }
//                }
            } errorBlock:^(int errorCode, NSString *errorMessage) {
                [self.loadingIndicator stopAnimating];
                [[[UIAlertView alloc] initWithTitle:@"Indholdet er ikke længere tilgængeligt" message:nil delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil] show];
                [self startScannerScanning];
            }];
            
#else
            //no IMF
            BAWebBrowserViewController* browser = [BAWebBrowserViewController new];
            [self presentViewController:browser animated:YES completion:nil];
            [browser setUrl:value];
#endif
        
        } else if (BAScannerCodeTypeCode39) {
            [self playSnapShotSound];
            [self stopScannerScanning]; //[self.readerView stop];
            self.scanContainerView.hidden = YES;
            
            [self.loadingIndicator startAnimating];
            
            [BARPCManager getObjectByBarcodeIdFromView:self
                                        materialnumber:value
                                       sendHoldingInfo:NO //FIXME: should we?
                                           resultBlock:^(BAFullRecord *fullRecord) {
                                               UIViewController<BAMaterialViewControllerProtocol>* mvc = [[BARootViewController instance] createMaterialViewController];
                                               [mvc showFullRecord:fullRecord withCoverUrl:nil currentImage:nil availability:nil];
                                               [self.navigationController pushViewController:mvc animated:YES];
                                               [self.loadingIndicator stopAnimating];
                                               
                                           }
                                            errorBlock:^(int errorCode, NSString *errorMessage) {
                                                NSString* usermsg = [NSString stringWithFormat:@"Stregkoden kunne ikke benyttes. %@",errorMessage];
                                                
                                                UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Scanner"
                                                                                                message:usermsg
                                                                                               delegate:self
                                                                                      cancelButtonTitle:@"OK"
                                                                                      otherButtonTitles:nil];
                                                [alert show];
                                                [self.loadingIndicator stopAnimating];
                                            }
             ];
        }
    }
}

-(void)playSnapShotSound
{
    AudioServicesPlaySystemSound(cameraSoundRef);

}

#pragma mark - ZBAR delegate methods
#ifdef BA_USE_ZBAR_SCANNER
- (void) readerView: (ZBarReaderView*) view
     didReadSymbols: (ZBarSymbolSet*) syms
          fromImage: (UIImage*) img
{
    for(ZBarSymbol *sym in syms) {
        NSString* decoded_text = sym.data;
        if ([decoded_text length]>0) {
            DLog(@"decoded %@: %@",sym.typeName, decoded_text);
            
            if (sym.type == ZBAR_QRCODE) {
                NSURL* urlcheck = [NSURL URLWithString:decoded_text];
                if (urlcheck!=nil && ![urlcheck isFileURL]) {
                    [self scannerScannedCode:BAScannerCodeTypeQRCode value:decoded_text];
                    break;
                     
                }
            } else if (sym.type == ZBAR_CODE39) {
                [self scannerScannedCode:BAScannerCodeTypeCode39 value:decoded_text];
                [self.readerView flushCache];
                
            } else if (sym.type == ZBAR_CODE128) {
                [self scannerScannedCode:BAScannerCodeTypeCode128 value:decoded_text];
                [self.readerView flushCache];
            }

            break;
        }
    }

}
#endif

#pragma mark - AVCaptureMetadataOutputObjectsDelegate methods

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    //DLog(@"capture objs: %@",metadataObjects);
    for(AVMetadataObject *current in metadataObjects) {
        if([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) {
            /*
            if([self.delegate respondsToSelector:@selector(scanViewController:didSuccessfullyScan:)]) {
                NSString *scannedValue = [((AVMetadataMachineReadableCodeObject *) current) stringValue];
                [self.delegate scanViewController:self didSuccessfullyScan:scannedValue];
            }*/
            AVMetadataMachineReadableCodeObject* codeobj = (AVMetadataMachineReadableCodeObject*)current;
            if ([codeobj.type isEqualToString:AVMetadataObjectTypeCode39Code]) {
                NSString* materialID = codeobj.stringValue;
                if ([materialID length]>0) {
                    DLog(@"got code-39: %@",materialID);
                    [self scannerScannedCode:BAScannerCodeTypeCode39 value:materialID];
                }
            } else if ([codeobj.type isEqualToString:AVMetadataObjectTypeQRCode]) {
                NSString* url = codeobj.stringValue;
                if ([url length]>0) {
                    DLog(@"got qr: %@",url);
                    [self scannerScannedCode:BAScannerCodeTypeQRCode value:url];
                }
            } else if ([codeobj.type isEqualToString:AVMetadataObjectTypeCode128Code]) {
                NSString* codecode = codeobj.stringValue;
                if ([codecode length]>0) {
                    DLog(@"got code-128: %@",codecode);
                    [self scannerScannedCode:BAScannerCodeTypeCode128 value:codecode];
                }
            }
        }
    }}

#pragma mark - Alert View delegate methods

-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    //assuming alertview only displayed when error
    self.scanContainerView.hidden = NO;
    [self startScannerScanning]; //[self.readerView start];
#ifdef BA_USE_ZBAR_SCANNER
    [self.readerView flushCache];
#endif
}

#pragma mark - Flyout menu

BA_FLYOUT_MENU_ADD_CALLBACK

- (void)enableUserInteraction
{
    self.view.userInteractionEnabled = YES;
    self.tabBarController.tabBar.userInteractionEnabled = YES;
}

- (void)disableUserInteraction
{
    self.view.userInteractionEnabled = NO;
    self.tabBarController.tabBar.userInteractionEnabled = NO;
}

@end
